using System;
using System.Collections.Generic;
using System.Text;
using Sedna.Core.Common;
using Sedna.Core.Common.Objects.Navigation;
using Sedna.Core.Controller;

namespace Sedna.Core.Security
{
    /// <summary>
    /// Defines what action should be executed
    /// </summary>
    public class DefaultActionResolver : IActionResolver
    {
        protected const String CREATE_ACTION = "Create";
        protected const String LOAD_SELF_ACTION = "LoadSelf";
        protected const String LOAD_OTHERS_ACTION = "LoadOthers";
        
        private String idKey = "id";
        private String actionKey = "action";

        private Scope scope = Scope.Request;

        # region Properties

        public string IdKey
        {
            get { return idKey; }
            set { idKey = value; }
        }

        public string ActionKey
        {
            get { return actionKey; }
            set { actionKey = value; }
        }

        public String Id
        {
            get { return ScopePathParser.Instance.GetScopedValue(scope, idKey) as String; }
        }

        public String Action
        {
            get { return ScopePathParser.Instance.GetScopedValue(scope, actionKey) as String; }
        }

        public Scope Scope
        {
            get { return scope; }
            set { scope = value; }
        }

        # endregion

        public virtual String Resolve(IExecutionContext executionContext)
        {
            if (String.IsNullOrEmpty(Action))
            {
                if (String.IsNullOrEmpty(Id))
                    return CREATE_ACTION;

                return (IsSelf(executionContext)) ? LOAD_SELF_ACTION : LOAD_OTHERS_ACTION;
            }
            else
            {
                if ("create".Equals(Action.ToLower()) && !String.IsNullOrEmpty(Id))
                {
                    FailedToResolveActionNotification();
                    
                    // override the method above if you don't wanna get exception
                    throw new SednaException(SednaExceptionCodes.FailedToResolveAction);
                }

                if ("load".Equals(Action.ToLower()))
                {
                    if (String.IsNullOrEmpty(Id))
                    {
                        FailedToResolveActionNotification();
                        
                        // override the method above if you don't wanna get exception
                        throw new SednaException(SednaExceptionCodes.FailedToResolveAction);   
                    }

                    return (IsSelf(executionContext)) ? LOAD_SELF_ACTION : LOAD_OTHERS_ACTION;
                }
                
                return Action;                    
            }
        }

        /// <summary>
        /// By default this method does nothing, but its behaviour
        /// can be overridden in childs in order to return special action
        /// or redirect to another page with certain message.
        /// </summary>
        protected virtual void FailedToResolveActionNotification()
        {            
        }
        
        /// <summary>
        /// Override this method if you wanna do some weird check 
        /// if a principle owns the object he is about to load
        /// </summary>
        protected virtual bool IsSelf(IExecutionContext executionContext)
        {
            return "self".Equals(Id.ToLower());
        }
    }
}
